package com.ccteam.shared.data

import com.ccteam.model.Resource
import com.ccteam.network.ApiError
import com.ccteam.network.ApiResult
import kotlinx.coroutines.flow.flow

/**
 * @author Xiaoc
 * @since 2021/2/20
 *
 * 仅依靠网络的的Resource决策操作，它与 [Resource] 状态紧密相连
 *
 * 提供一个 [asFlow] 方法，将打包为一个Flow流，并进行以下操作
 * 1.先提供一个数据为空的等待状态（该步骤已被具体业务具体代替）
 * 2.进行网络请求返回数据
 * 7.提供网络请求返回的数据状态，如果请求网络失败则提供失败状态
 *
 * 注：该类基于单一数据源 原理，因为多数据源可能会导致的数据不正确，该类的数据源统一设定为：网络请求
 *
 * @param RequestType 请求网络等内容时请求的类型
 */
abstract class BaseOnlyNetworkBoundResource<RequestType> {

    fun asFlow() = flow {
        when(val response = fetchFromNetwork()){
            is ApiResult.Success ->{
                emit(Resource.Success(processResponse(response)))
            }
            is ApiResult.Empty ->{
                emit(Resource.Error(ApiError.dataIsNullCode,ApiError.dataIsNull.errorMsg,null))
            }
            is ApiResult.Failure ->{
                onFetchFailed()
                emit(Resource.Error(ApiError.serverErrorCode,response.errorMsg,null))
            }
        }
    }

    /**
     * 当出现请求失败时需要做的处理（默认不做处理）
     */
    protected open fun onFetchFailed(){}

    protected open fun processResponse(response: ApiResult.Success<RequestType>) = response.data

    /**
     * 从网络上获取数据
     * @return ApiResult<RequestType> 具体Api返回的内容
     */
    protected abstract suspend fun fetchFromNetwork(): ApiResult<RequestType>
}